import xlrd
import random
import copy

def read_excel(filename,sheetname):
    book = xlrd.open_workbook(filename)
    sheet = book.sheet_by_name(sheetname)
    puck = []
    rows = sheet.nrows #获取行数
    for r in range(rows): #读取每一行的数据
        r_values = sheet.row_values(r)
        puck.append(r_values)
    return puck
P = read_excel('Pucks(1).xlsx','Sheet1')
G = read_excel('InputData2.xlsx','Gates')

#适应度评价
def evaluate1(gene):
    ans = 0
    ans2 = 0
    gates = [[] for _ in range(70)]
    gs = [[] for _ in range(70)]  ##gs[i]表示登机口i上已成功安排的航班
    for i in range(len(gene)):
        gates[gene[i]].append(i)  ##gates数组表示每个等级口上的航班
    for i in range(1,70):
        if len(gates[i]) == 0:
            ans2 += 1
        for j in range(len(gates[i])):  ##对每个等级口上的每个航班进行判断（未加优先级操作，可改为时间较短的优先）
            [a,b] = [Pucks[gates[i][j]].arriveMoment,Pucks[gates[i][j]].setoffMoment]  ##航班的到达时间和起飞时间
            flag = True
            for k in range(len(gs[i])):  ##判断该航班是否和已成功安排航班冲突
                if (a >= gs[i][k][0] and a <= gs[i][k][1] + 45) or (b >= gs[i][k][0] and b <= gs[i][k][1] + 45):
                    flag = False
                    break
            if flag:
                ans += 1
                gs[i].append([a,b])  ##若不冲突则安排
    return [ans + (ans2 * 0.01),gates,gs]
##航班类
class Puck():
    def __init__(self, arriveMoment, arriveFlight, arriveType, planeType, setoffMoment, setoffFlight, setoffType):
        self.arriveMoment = int(arriveMoment)
        self.arriveFlight = arriveFlight
        if arriveType == 'D':
            self.arriveType = 0
        else :
            self.arriveType = 1
        if planeType == 'N':
            self.planeType = 0
        else:
            self.planeType = 1
        self.setoffMoment = int(setoffMoment)
        self.setoffFlight = setoffFlight
        if setoffType == 'D':
            self.setoffType = 0
        else:
            self.setoffType = 1
        self.T = self.arriveType * 4 + self.setoffType * 2 + self.planeType
##登机口类
class Gate():
    def __init__(self, number, arriveType, setoffType, planeType):
        self.number = number
        self.arriveType = arriveType
        self.setoffType = setoffType
        self.planeType = planeType
#粒子
class Particle():
    def __init__(self):
        self.gene = [0] * len(Pucks)
        for i in range(len(Pucks)):
            r = random.randint(0, len(Gate[Pucks[i].T])-1)
            self.gene[i] = Gate[Pucks[i].T][r]
        self.bestgene = self.gene
        self.fitness = 0
        self.bestfitness = 0
        self.gates = [[] for _ in range(70)]
        self.gs = [[] for _ in range(70)]
    def mutation(self):
        r1 = random.randint(0,len(Pucks)-1)
        r2 = random.randint(0, len(Gate[Pucks[r1].T])-1)
        self.gene[r1] = Gate[Pucks[r1].T][r2]
#获取航班与登机口信息
def getP_G():
    Pucks = []
    for i in range(len(P)):
        Pucks.append(Puck(P[i][2],P[i][3],P[i][4],P[i][5],P[i][7],P[i][8],P[i][9]))
    Gate = [[] for _ in range(8)]
    for i in range(2,len(G)):
        if G[i][5] == 'N':
            if G[i][3].find('D')!= -1 and G[i][4].find('D')!= -1:
                Gate[0].append(i)
            if G[i][3].find('D')!= -1 and G[i][4].find('I')!= -1:
                Gate[2].append(i)
            if G[i][3].find('I')!= -1 and G[i][4].find('D')!= -1:
                Gate[4].append(i)
            if G[i][3].find('I')!= -1 and G[i][4].find('I')!= -1:
                Gate[6].append(i)
        else:
            if G[i][3].find('D')!= -1 and G[i][4].find('D')!= -1:
                Gate[1].append(i)
            if G[i][3].find('D')!= -1 and G[i][4].find('I')!= -1:
                Gate[3].append(i)
            if G[i][3].find('I')!= -1 and G[i][4].find('D')!= -1:
                Gate[5].append(i)
            if G[i][3].find('I')!= -1 and G[i][4].find('I')!= -1:
                Gate[7].append(i)
    return [Pucks,Gate]
[Pucks,Gate] = getP_G()
pop_size = 100
bst = [0] * len(Pucks)
best_fitness = 0
population = []
#交叉函数
def genetic(c1, c2):
    if c1 is None or c2 is None:
        return
    pos_num1 = random.randint(0, len(P) - 1)
    pos_num2 = random.randint(0, len(P) - 1)
    if pos_num1 > pos_num2:
        temp = pos_num2
        pos_num2 = pos_num1
        pos_num1 = temp
    for i in range(pos_num1, pos_num2):
        c1[i] = c2[i]

    return [copy.deepcopy(c1),copy.deepcopy(c2)]
#种群初始化
def init():
    global bst
    global best_fitness
    global population
    for _ in range(pop_size):
        population.append(Particle())
    for i in range(pop_size):
        [population[i].fitness,population[i].gates,population[i].gs] = evaluate1(population[i].gene)
        population[i].bestfitness = population[i].fitness
        if population[i].fitness > best_fitness:
            best_fitness = population[i].fitness
            bst = copy.deepcopy(population[i].gene)
#种群进化
def evolve():   ##暂时采用随机选择某一粒子与历史全局最优交叉（需改为轮盘选择法试试）
    global population
    global bst
    global best_fitness
    total_f = 0
    q = [0] * (pop_size + 1)
    for i in range(pop_size):
        total_f += population[i].fitness
    q[1] = population[0].fitness / total_f
    for i in range(2,pop_size+1):
        q[i] = q[i-1] + (population[i-1].fitness / total_f)
    _population = [0] * pop_size
    for i in range(pop_size):
        _population[i] = Particle()
    for i in range(50):
        r1 = random.random()
        r2 = random.random()
        for j in range(1,pop_size+1):
            if r1 > q[j-1] and r1 < q[j]:
                r1 = j-1
                break
        for j in range(1,pop_size+1):
            if r2 > q[j-1] and r2 < q[j]:
                r2 = j-1
                break
        [_population[i].gene, _population[i+50].gene] = genetic(population[r1].gene,bst)
        _population[i].mutation()
        _population[i+50].mutation()
    for i in range(pop_size):
        population[i].gene = copy.deepcopy(_population[i].gene)
        [population[i].fitness,population[i].gates,population[i].gs] = evaluate1(population[i].gene)
        if population[i].fitness > best_fitness:
            best_fitness = population[i].fitness
            bst = copy.deepcopy(population[i].gene)

def GA():
    global population
    global bst
    global best_fitness
    init()
    for i in range(300):
        evolve()
        print(bst)
        print(best_fitness)

    gates = [[] for _ in range(70)]
    gs = [[] for _ in range(70)]
    [best_fitness,gates,gs] = evaluate1(bst)
    for i in range(1,70):
        print(gs[i])

GA()
# bst = [49, 37, 66, 66, 15, 40, 7, 39, 25, 7, 9, 22, 23, 54, 21, 40, 22, 35, 22, 40, 42, 23, 8, 22, 65, 7, 54, 43, 48, 47, 53, 33, 20, 8, 17, 47, 20, 11, 20, 42, 22, 7, 38, 55, 20, 21, 18, 46, 33, 16, 42, 48, 42, 39, 7, 44, 22, 18, 21, 7, 42, 41, 41, 21, 22, 49, 21, 12, 33, 9, 8, 9, 21, 37, 17, 22, 39, 37, 19, 22, 31, 25, 20, 12, 17, 36, 22, 21, 40, 52, 20, 8, 29, 41, 54, 42, 22, 9, 42, 30, 38, 51, 22, 39, 22, 65, 9, 34, 8, 25, 19, 11, 9, 30, 22, 39, 32, 5, 8, 41, 7, 46, 7, 7, 7, 41, 17, 43, 7, 63, 8, 20, 5, 20, 41, 7, 42, 6, 21, 66, 15, 2, 20, 42, 7, 39, 42, 19, 39, 45, 7, 20, 8, 23, 9, 9, 34, 42, 35, 40, 22, 12, 7, 42, 39, 16, 7, 7, 37, 8, 43, 39, 7, 22, 6, 22, 9, 50, 67, 20, 22, 32, 29, 59, 14, 7, 37, 39, 34, 38, 34, 11, 22, 54, 7, 52, 19, 44, 22, 46, 56, 27, 56, 20, 50, 7, 20, 19, 35, 38, 22, 48, 66, 14, 45, 20, 20, 21, 46, 54, 46, 20, 41, 10, 52, 15, 44, 7, 8, 30, 11, 38, 36, 22, 34, 7, 32, 21, 12, 37, 45, 22, 17, 21, 30, 8, 6, 34, 31, 12, 4, 39, 9, 23, 40, 40, 22, 3, 40, 41, 7, 69, 40, 7, 40, 41, 39, 63, 7, 7, 9, 7, 62, 7, 31, 21, 41, 33, 35, 42, 29, 13, 7, 13, 6, 7, 20, 8, 22, 32, 34, 19, 10, 7, 30, 51, 7, 48, 56, 31, 22, 31, 45]
# f = evaluate1(bst)